package com.tiger.poker.util;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.tiger.poker.controller.WebSocket21;
import com.tiger.poker.entity.Game21Vo;
import org.springframework.util.StringUtils;

import javax.websocket.Session;
import java.io.IOException;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author Joy on 2019/2/12 9:38
 */
public class Game21Util {
    private static final int JOIN_GAME = 0;
    private static final int JOIN_SUCCESS = -1;
    private static final int JOIN_FAILED = -2;
    private static final int GET_CARD = 1;
    private static final int SHOW_CARD = 2;
    private static final int CARD_COMPARE = 3;
    public static final int SHOW_MESSAGE = 88;
    public static final int UPDATE_DATA = 99;
    public static final int RESET_GAME = 100;

    public static final ObjectMapper MAPPER = new ObjectMapper();

    public static void resolveMessage(int type, String content, Session session) throws IOException {


        if (type == JOIN_GAME) {
            joinGame(content, session);
        } else {
            Game21Vo game21Vo = MAPPER.readValue(content, Game21Vo.class);
            game21Vo.setSession(session);
            WebSocket21.GAME_21_VO_SET.remove(game21Vo);
            WebSocket21.GAME_21_VO_SET.add(game21Vo);
            WebSocketUtil.sendMessageBatch21(WebSocket21.GAME_21_VO_SET,
                    UPDATE_DATA + WebSocket21.MESSAGE_SEPARATOR + MAPPER.writeValueAsString(WebSocket21.GAME_21_VO_SET));
            switch (type) {
                case GET_CARD:
                    WebSocketUtil.sendMessageBatch21(WebSocket21.GAME_21_VO_SET,
                            SHOW_MESSAGE + WebSocket21.MESSAGE_SEPARATOR + game21Vo.getName() + " 要了一张牌");
                    break;
                case SHOW_CARD:
                    boolean compare = true;
                    for (Game21Vo vo : WebSocket21.GAME_21_VO_SET) {
                        if (StringUtils.hasText(vo.getName()) && vo.getStatus() != 2) {
                            compare = false;
                        }
                    }
                    if (compare) {
                        WebSocket21.GAME_21_VO_SET.forEach(vo -> vo.setStatus(CARD_COMPARE));
                        String result = MAPPER.writeValueAsString(cardCompare());
                        WebSocketUtil.sendMessageBatch21(WebSocket21.GAME_21_VO_SET, CARD_COMPARE + WebSocket21.MESSAGE_SEPARATOR + result);
                    } else {
                        WebSocketUtil.sendMessageBatch21(WebSocket21.GAME_21_VO_SET,
                                SHOW_MESSAGE + WebSocket21.MESSAGE_SEPARATOR + game21Vo.getName() + " 想要开牌");
                    }
                    break;
                case RESET_GAME:
                    WebSocket21.GAME_21_VO_SET.stream().filter(vo -> vo.getSession().equals(session)).forEach(vo -> game21Vo.setStatus(1));
                default:
            }

        }


    }

    private static class Game21Compare implements Comparator<Game21Vo> {

        @Override
        public int compare(Game21Vo o1, Game21Vo o2) {
            return o1.getNumbers().stream().reduce((x, y) -> x + y).orElse(0)
                    .compareTo(o2.getNumbers().stream().reduce((x, y) -> x + y).orElse(0));
        }
    }

    private static class Game21Predicate implements Predicate<Game21Vo> {

        @Override
        public boolean test(Game21Vo game21Vo) {
            return game21Vo.getNumbers().stream().reduce((x, y) -> x + y).orElse(0) <= 21;
        }
    }

    private static Object cardCompare() {
        Game21Vo winner;
        String winnerString;
        List<Game21Vo> small21 = WebSocket21.GAME_21_VO_SET.stream().filter(
                new Game21Predicate()).collect(Collectors.toList());
        if (small21.size() > 0) {
            Optional<Game21Vo> first = small21.stream().max(new Game21Compare());
            winner = first.get();
        } else {
            Optional<Game21Vo> min = WebSocket21.GAME_21_VO_SET.stream().min(new Game21Compare());
            winner = min.orElse(new Game21Vo().setName("null"));
        }


        String userName = winner.getName();
        int score = winner.getNumbers().stream().reduce((x, y) -> x + y).orElse(0);
        winnerString = userName + " 获得了 " + score + " 分,取得最终胜利";


        Map<String, Object> map = new HashMap<>(4);
        map.put("winnerString", winnerString);

        List<String> stringList = WebSocket21.GAME_21_VO_SET.stream().map(vo -> {
            StringJoiner stringJoiner = new StringJoiner(" ");
            vo.getNumbers().forEach(number -> stringJoiner.add(number.toString()));
            return vo.getName() + " :  " + stringJoiner.toString();
        }).collect(Collectors.toList());
        map.put("numberList", stringList);

        return map;
    }


    private static void joinGame(String name, Session session) {
        Game21Vo game21Vo = new Game21Vo(session);
        game21Vo.setName(name);
        boolean nameExist = WebSocket21.GAME_21_VO_SET.stream().
                anyMatch(v -> game21Vo.getName().equals(v.getName()));
        if (nameExist) {
            WebSocketUtil.sendMessage(session, JOIN_FAILED + WebSocket21.MESSAGE_SEPARATOR);
        } else {
            WebSocketUtil.sendMessage(session, JOIN_SUCCESS + WebSocket21.MESSAGE_SEPARATOR);
            WebSocketUtil.sendMessageBatch21(WebSocket21.GAME_21_VO_SET,
                    SHOW_MESSAGE + WebSocket21.MESSAGE_SEPARATOR + game21Vo.getName() + " 加入了游戏");
            WebSocket21.GAME_21_VO_SET.add(game21Vo);
        }
    }

}
